----------------------------------------------------------------------
-- Code book for vector quantization
-- Stephen West, James Carroll
-- BYU ECEn 620, October 2008
----------------------------------------------------------------------
Library ieee;
	use ieee.std_logic_1164.all;
	use ieee.numeric_std.all;
	
entity CodeBook is
	generic(
		word_length:integer:=8;
		code_vector_length:integer:=16;
		system_word_length:integer:=12
		--index_in:integer:=0
	);
	port(
		clk, config_ctrl_in, lsb_in, index_data:in std_logic;
		config_data:in std_logic_vector(code_vector_length-1 downto 0);
		config_ctrl_out, lsb_out,index_bits: out std_logic;
		code_bits: out std_logic_vector(code_vector_length-1 downto 0)
	);
end entity;

architecture CodeBook of CodeBook is
	type CodeBookArray is array(code_vector_length-1 downto 0) of std_logic_vector(system_word_length-1 downto 0);
	type states is (startup,configing, waiting, working);
	signal ns,cs:states:=startup;
	signal CodeBook: CodeBookArray:=(others=>(others=>'0'));
	signal counter_word, counter_vector: integer:=0;
	signal index:std_logic_vector(system_word_length-1 downto 0):=(others=>'0');--td_logic_vector(to_unsigned(index_in,system_word_length));
begin
	process(clk,counter_word)
	begin
		if clk'event and clk='1' then
			if (ns=startup or ns=waiting) then
				counter_word<=0;
				counter_vector<=0;
			else--cs = configing or working
				if counter_word<(system_word_length-1) then
					counter_word<=counter_word+1;
				else
					counter_word<=0;
				end if;
			end if;
		end if;
	end process;
	code_book_ger:for N in 0 to Code_vector_length-1 generate
		process(clk,ns,counter_word,config_data)
		begin
			if clk'event and clk='1' then
				if ns=configing then
					CodeBook(N)(counter_word)<=config_data(N);
				end if;
			end if;
		end process;
	end generate;
	process(clk,ns,counter_word,index_data)
	begin
		if(clk'event and clk='1') then
			if ns=configing then
				index(counter_word)<=index_data;
			end if;
		end if;
	end process;
	
	process(clk, cs,ns)
	begin
		if clk'event and clk='1' then
			cs<=ns;
		end if;
	end process;
	ns_logic:process(cs,config_ctrl_in,counter_word, lsb_in)
	begin
		ns<=cs;--default
		config_ctrl_out<='0';
		case cs is
		when startup=>
			if config_ctrl_in='1' then
				ns<=configing;
			end if;
		when configing=>
			if counter_word=word_length then
				ns<=waiting;
				config_ctrl_out<='1';
			end if;
		when waiting=>
			if (lsb_in='1') then
				ns<=working;
			end if;
		when working=>
			if config_ctrl_in='1' then
				ns<=configing;
			end if;
		end case;
	end process;
	
	CodeOut:for N in code_vector_length-1 downto 0 generate
		code_bits(N)<=CodeBook(N)(counter_word);
	end generate;
	index_bits<=index(counter_word);
	lsb_out<='1' when lsb_in='1' or (cs=working and counter_word=0)
		else '0';
end architecture;
